package borge.web.teamspirit.server;

import java.io.Serializable;
import java.util.List;

import borge.web.teamspirit.client.data.League;
import borge.web.teamspirit.client.data.LeagueDivision;
import borge.web.teamspirit.client.data.Match;
import borge.web.teamspirit.client.data.MatchPlayerStats;
import borge.web.teamspirit.client.data.Person;
import borge.web.teamspirit.client.data.Serie;
import borge.web.teamspirit.client.data.SerieStats;
import borge.web.teamspirit.client.data.Sport;
import borge.web.teamspirit.client.interfaces.PersistentData;
import borge.web.teamspirit.client.interfaces.PersistentData.DataKey;
import borge.web.teamspirit.client.servercomm.DBQuery;
import borge.web.teamspirit.client.servercomm.DBQueryResults;
import borge.web.teamspirit.client.servercomm.DataService;
import borge.web.teamspirit.client.servercomm.DBQueryResults.Result;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class DataServiceImpl extends RemoteServiceServlet implements
		DataService {

	private SessionHandler iSessionHandler;
	private DatabaseHandler iDbHandler;
	
	public DataServiceImpl(){
		
		
		iDbHandler = new DatabaseHandler();
		
	}
	
	private void initSessionHandler(){
		
		if(iSessionHandler == null)
			iSessionHandler = new SessionHandler(this.getThreadLocalRequest().getSession(true));
	}
	
	public DBQueryResults isFieldUnique(DBQuery aQuery){
		
		Result result = iDbHandler.getObjectList(aQuery);
		System.out.println("field is unique = " + !result.hasObjects());
		DBQueryResults res = new DBQueryResults(!result.hasObjects(), null);
		
		return res;
	}
	
	public DBQueryResults isSessionValid(String aId){
		
		System.out.println("isSessionValid");
		
		initSessionHandler();
		
		
		boolean valid = iSessionHandler.isValid(aId);
		
		if(valid){
			Person p = getSessionValue(Person.class.getName());
			if(p != null){
				DBQueryResults results = new DBQueryResults();
				results.addResult(DataKey.PERSON, new Result(p));
				System.out.println("valid session!");
				return results;
				
			}
		}

		return new DBQueryResults(false, null);
		
	}
	
	public DBQueryResults loginUser(String aUserName, String aPassword){
		
		System.out.println("loginUser");
		
		initSessionHandler();
		//iSessionHandler = new SessionHandler(this.getThreadLocalRequest().getSession());	
		System.out.println("loginUser u = " + aUserName + " p = " + aPassword);
		DBQuery query = new DBQuery(DataKey.PERSON, Person.class.getName());
		query.addFilter(Person.KEY_USERNAME, DBQuery.EQUALS, "unParam", "String", aUserName, DBQuery.AND);
		query.addFilter(Person.KEY_PASSWORD, DBQuery.EQUALS, "pwParam", "String", aPassword, null);
		
		
		Result result = iDbHandler.getObjectList(query);
		
		if(result.getResultList().size() > 0){
			System.out.println("query succeeded");
			// This seems a bit..strange
			Person person = (Person)result.getResultList().get(0);
			System.out.println("user " + person.getFirstName() + person.getLastName() + " logged in");
			iSessionHandler.saveObject(Person.class.getName(), person);
			System.out.println("session id = " + iSessionHandler.getSessionId());
			person.setSessionId(iSessionHandler.getSessionId());
			return new DBQueryResults(true, null);
		}
		
		return new DBQueryResults(false, null);
		
		
	}
	
	public DBQueryResults destroyUserSession(String aId){
		
		System.out.println("destroyUserSession");
		initSessionHandler();
		
		iSessionHandler.invalidate(aId);
		iSessionHandler = null;
		
		return new DBQueryResults(true, null);
		
	}
	
	public <T extends Serializable> T getSessionValue(String aKey){
	
		Object obj = iSessionHandler.getObject(aKey); 
		
		if(!(obj instanceof Serializable))
			return null;
		
		return (T)obj;
		
	}
	

	
	public void testCreateEntities(){
		iDbHandler.testCreateEntities();
	}
	
	public void testPrintEntities(){
		iDbHandler.testPrintEntities();
	}
	
	public DBQueryResults getObjectList(DBQuery aQuery){
		DBQueryResults results = new DBQueryResults();
		results.addResult(aQuery.getDataKey(), iDbHandler.getObjectList(aQuery));
		return results;
	}
	
	public DBQueryResults getObjectChildren(List<DBQuery> aQueries){
		
		DBQueryResults results = new DBQueryResults();
		for(DBQuery query : aQueries){
			
			Result result = iDbHandler.getObjectList(query);
			results.addResult(query.getDataKey(), result);
		}
		
		return results;
	}

	// Okey..to get all serie related stuff..
	public DBQueryResults getAllSerieData(DBQuery aQuery){
		
		System.out.println("getAllSerieData");
		// first get the serie
		Result result = iDbHandler.getObjectList(aQuery);
		Serie serie = (Serie)result.getResultList().get(0);
		
		DBQuery leagueDivQuery = new DBQuery(DataKey.LEAGUEDIVISION, LeagueDivision.class.getName());
		leagueDivQuery.addFilter("iEncodedKey", DBQuery.EQUALS, "leagueDivParam", "String", serie.getLeagueDivisionKey(), null);
		LeagueDivision ld = (LeagueDivision)iDbHandler.getObject(leagueDivQuery);
		serie.setLeagueDivision(ld);
		
		DBQuery leagueQuery = new DBQuery(DataKey.LEAGUE, League.class.getName());
		leagueQuery.addFilter("iEncodedKey", DBQuery.EQUALS, "leagueParam", "String", ld.getLeagueKey(), null);
		League league = (League)iDbHandler.getObject(leagueQuery);
		serie.setLeague(league);
		
//		DBQuery sportQuery = new DBQuery(DataKey.SPORT, Sport.class.getName());
//		leagueQuery.addFilter("iEncodedKey", DBQuery.EQUALS, "sportParam", "String", league.getSportKey(), null);
//		Sport sport = (Sport)iDbHandler.getObject(sportQuery);
//		league.setSport(sport);
		
		DBQuery query = new DBQuery(DataKey.MATCH, Match.class.getName());
		query.addFilter("iOwningSerieKey", DBQuery.EQUALS, "serieKey", "String", serie.getEncodedKey(), null);
		List<PersistentData> matches = iDbHandler.getObjectList(query).getResultList();
		serie.setMatches(matches);
		
		/*DBQuery commentQuery = new DBQuery(DataKey.COMMENT, Comment.class.getName());
		commentQuery.addFilter("iParentKey", DBQuery.EQUALS, "ownerParam", "String", serie.getEncodedKey(), null);
		Result res = iDbHandler.getObjectList(commentQuery);
		
		serie.setComments(res.getResultList());*/
		
		DBQueryResults results = new DBQueryResults();
		results.addResult(DataKey.SERIE, result);
		
		return results; 
		
	}
	
	public DBQueryResults getAllSeriesStats(List<DBQuery> aQueries){
		
		System.out.println("getAllSeriesStats");
		DBQueryResults results = new DBQueryResults();
		
		Result result = new Result();
		for(DBQuery query : aQueries){
			Result res = getSeriePlayersStatsInternal(query);
			result.addResultData(res);
		}
		// we're gonna need more info here..like serie placement
		
		results.addResult(DataKey.TOTALSTATS, result);
		return results;
	}
	
	public DBQueryResults getSerieStats(DBQuery aQuery){
		
		DBQueryResults results = new DBQueryResults();
		Result res = getSeriePlayersStatsInternal(aQuery);
		results.addResult(DataKey.SERIESTATS, res);
		return results;
		
	}
	
	private Result getSeriePlayersStatsInternal(DBQuery aQuery){
		
		System.out.println("get serie stats");
		
		String serieKey = (String)aQuery.getParamValues().get(0);
		
		DBQuery query = new DBQuery(DataKey.MATCH, Match.class.getName());
		query.addFilter("iOwningSerieKey", DBQuery.EQUALS, "serieKey", "String", serieKey, null);
		
		Result matchesResult = iDbHandler.getObjectList(query);
		List<PersistentData> matches = matchesResult.getResultList();
		
		SerieStats serieStats = new SerieStats();
		serieStats.iSerieKey = serieKey;
		
		for(PersistentData pd : matches){
			
			Match m = (Match)pd;
			
			serieStats.iGoalsMade += m.getOurScore();
			serieStats.iOppGoals += m.getOpponentScore();
			if(m.getResult() == Match.Result.WIN)
				serieStats.iMatchesWon++;
			else if(m.getResult() == Match.Result.LOSS)
				serieStats.iMatchesLost++;
			else
				serieStats.iMatchesDraw++;
			
			query = new DBQuery(DataKey.MATCHSTATS, MatchPlayerStats.class.getName());
			query.addFilter("iMatchKey", DBQuery.EQUALS, "matchKey", "String", m.getEncodedKey(), null);
			List<PersistentData> matchStats = iDbHandler.getObjectList(query).getResultList();
			
			for(PersistentData pd2 : matchStats){
				
				MatchPlayerStats mps = (MatchPlayerStats)pd2;
				serieStats.addPlayerStats(mps.getPlayerKey(), mps.getGoals(), mps.getAssists(), mps.getRedCard(), mps.getYellowCard());
				if(mps.getRedCard())
					serieStats.iRedCards++;
				if(mps.getYellowCard())
					serieStats.iYellowCards++;
				
			}
		}
		
		Result result = new Result();
		result.addObject(serieStats);
		
		return result;
	}
	

//	
//	// SAVE METHODS
//    public DBQueryResult saveMatch(Match aMatch) {
//        
//    	// let's have some fuuun
//    	
//    	
//        DBQueryResult result = iDbHandler.saveObject(aMatch);
//        y 
//        return result;
//    }
//
//    public DBQueryResult saveSerie(Serie aSerie) {
//        
//        DBQueryResult result = iDbHandler.saveObject(aSerie);
//        
//        return result;
//    }
//
//    public DBQueryResult savePlayer(TeamPlayer aPlayer) {
//        
//        DBQueryResult result = iDbHandler.saveObject(aPlayer);
//        
//        return result;
//    }
//    
//
//    public DBQueryResult saveNews(News aNews) {
//        
//        DBQueryResult result = iDbHandler.saveObject(aNews);
//        
//        return result;
//    }
//
//    public DBQueryResult saveEvent(Event aEvent) {
//        
//        DBQueryResult result = iDbHandler.saveObject(aEvent);
//        
//        return result;
//    }
    
    // END SAVE METHODS
    
    // DELETE METHODS 
     
    public <T extends PersistentData> DBQueryResults deleteObject(Class<T> aClass, Object aKey) {
        
    	return iDbHandler.deleteObject(aClass, aKey);
        
    }
    
//    public DBQueryResult deletePlayer(TeamPlayer aPlayer) {
//        
//        return deleteObject(TeamPlayer.class, aPlayer.getEncodedKey());
//        
//        
//        
//    }
//    
//    public DBQueryResult deleteSerie(Serie aSerie) {
//        
//        //return deleteObject(Serie.class, aSerie.getSerieId());
//    	return null;
//    }
//    
//    public DBQueryResult deleteMatch(Match aMatch) {
//        //return deleteObject(Match.class, aMatch.getEncodedKey());
//    	return null;
//    }
//    
//    public DBQueryResult deleteNews(News aNews) {
//        //return deleteObject(News.class, aNews.getNewsId());
//    	return null;
//        
//    }
//    
//    public DBQueryResult deleteEvent(Event aEvent) {
//        //return deleteObject(Event.class);
//        return null;
//        
//    }
    
    // END DELETE METHODS
    
    public DBQueryResults genericQuery(DBQuery aQuery){
        
        return null;
    }

	@Override
	public <T extends PersistentData> DBQueryResults saveObject(T aObject) {
		// TODO Auto-generated method stub
		DBQueryResults res = iDbHandler.saveObject(aObject);
		return res;
	}

	@Override
	public DBQueryResults deleteObject(DBQuery aQuery) {
		// TODO Auto-generated method stub
		
		
		
		return null;
	}
    	
}